/**
 *
 * @author ronald
 */
package com.click.app.webapp.producers;

import com.click.app.model.Material;
import com.click.app.model.PurchaseDetail;
import com.click.app.service.MaterialManager;
import com.click.app.service.PurchaseDetailManager;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jfree.data.category.DefaultCategoryDataset;

import de.laures.cewolf.DatasetProduceException;
import de.laures.cewolf.DatasetProducer;
import java.util.ArrayList;
import java.util.List;

public class PageViewCountData implements DatasetProducer, Serializable {

    private static final Log log = LogFactory.getLog(PageViewCountData.class);
    private PurchaseDetailManager purchaseDetailManager;
    private MaterialManager materialManager;

    // These values would normally not be hard coded but produced by
    // some kind of data source like a database or a file
    private final String[] categories = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
    private boolean years;
    private Long[] materialsIds;
    private Date initDate;
    private Date endDate;

    public PageViewCountData(MaterialManager materialManager, PurchaseDetailManager purchaseDetailManager, Long[] materials, boolean years, Date initDate, Date endDate) {
        this.materialManager = materialManager;
        this.purchaseDetailManager = purchaseDetailManager;
        this.materialsIds = materials;
        this.years = years;
        this.initDate = initDate;
        this.endDate = endDate;
    }

    /**
     *  Produces some random data.
     */
    public Object produceDataset(Map params) throws DatasetProduceException {
        log.debug("producing data.");
        DefaultCategoryDataset dataset = new DefaultCategoryDataset() {

            /**
             * @see java.lang.Object#finalize()
             */
            protected void finalize() throws Throwable {
                super.finalize();
                log.debug(this + " finalized.");
            }
        };
        if (!years) {
            int month = initDate.getMonth();
            int year = initDate.getYear() + 1900;
            System.out.println("month: " + month + ", year: " + year);
            List<Integer> categoriesM = new ArrayList<Integer>();
            categoriesM.add(month * 10000 + year);
            int endMonth = endDate.getMonth();
            int endYear = endDate.getYear() + 1900;
            System.out.println("endmonth: " + endMonth + ", endyear: " + endYear);
            while (month != endMonth || year != endYear) {
                if (++month == 12) {
                    month = 0;
                    year++;
                }
                System.out.println("month: " + month + ", year: " + year);
                categoriesM.add(month * 10000 + year);
            }
            for (Long id : materialsIds) {
                Material material = materialManager.get(id);
                List<PurchaseDetail> purchasesDetails = purchaseDetailManager.findByMaterialPeriod(id, initDate, endDate);

                for (Integer i : categoriesM) {
                    int m = i / 10000;
                    int y = i % 10000;
                    Double totalPrice = 0D;
                    List<PurchaseDetail> purchasesDetailsRemove = new ArrayList<PurchaseDetail>();
                    for (PurchaseDetail pD : purchasesDetails) {
                        if (pD.getPurchase().getDate().getMonth() == m) {
                            totalPrice = totalPrice + pD.getTotalPrice();
                            purchasesDetailsRemove.add(pD);
                        } else {
                            break;
                        }
                    }
                    purchasesDetails.removeAll(purchasesDetailsRemove);
                    dataset.addValue(totalPrice, material.getName() + " [" + id + "]", categories[m] + "-" + y);
                }
            }
        } else {
            int year = initDate.getYear() + 1900;
            List<Integer> categoriesY = new ArrayList<Integer>();
            categoriesY.add(year);
            int endYear = endDate.getYear() + 1900;
            while (year != endYear) {
                categoriesY.add(++year);
            }
            for (Long id : materialsIds) {
                Material material = materialManager.get(id);
                List<PurchaseDetail> purchasesDetails = purchaseDetailManager.findByMaterialPeriod(id, initDate, endDate);

                for (Integer i : categoriesY) {
                    Double totalPrice = 0D;
                    List<PurchaseDetail> purchasesDetailsRemove = new ArrayList<PurchaseDetail>();
                    for (PurchaseDetail pD : purchasesDetails) {
                        if (pD.getPurchase().getDate().getYear() == i - 1900) {
                            totalPrice = totalPrice + pD.getTotalPrice();
                            purchasesDetailsRemove.add(pD);
                        } else {
                            break;
                        }
                    }
                    purchasesDetails.removeAll(purchasesDetailsRemove);
                    dataset.addValue(totalPrice, material.getName() + " [" + id + "]", i);
                }
            }
        }
        return dataset;
    }

    /**
     * This producer's data is invalidated after 5 seconds. By this method the
     * producer can influence Cewolf's caching behaviour the way it wants to.
     */
    public boolean hasExpired(Map params, Date since) {
        log.debug(getClass().getName() + "hasExpired()");
        return (System.currentTimeMillis() - since.getTime()) > 5000;
    }

    /**
     * Returns a unique ID for this DatasetProducer
     */
    public String getProducerId() {
        return "PageViewCountData DatasetProducer";
    }

    /**
     * @see java.lang.Object#finalize()
     */
    protected void finalize() throws Throwable {
        super.finalize();
        log.debug(this + " finalized.");
    }

} 
